/*
 * Copyright (C) 2012 mAPPn.Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mol.market.common.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;

/**
 * 滑动控件
 * 
 * @author licong
 * @date 2012-2-20
 * @since Version 0.9.2
 */
public class GalleryEx extends ViewGroup {
    private GestureDetector gesture;
    private boolean fling;
    private Scroller scroller;
    private OnScreenChangeListener onScreenChangeListener;

    public GalleryEx(Context context) {
        super(context);
        gesture = new GestureDetector(context, new GestureListener());
        scroller = new Scroller(context);
    }

    public GalleryEx(Context context, AttributeSet attrs) {
        super(context, attrs);
        gesture = new GestureDetector(context, new GestureListener());
        scroller = new Scroller(context);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        for (int i = 0, count = getChildCount(); i < count; i++) {
            View child = (View) getChildAt(i);
            child.layout(getWidth() * i, 0, getWidth() * (i + 1), getHeight());
            child.measure(r - l, b - t);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        gesture.onTouchEvent(ev);
        
        switch (ev.getAction()) {
        case MotionEvent.ACTION_MOVE:
            break;
            
        case MotionEvent.ACTION_UP:
            if (!fling) {
                scrollToScreen(0, false);
            }
            fling = false;
            break;

        case MotionEvent.ACTION_DOWN:
            break;
        }
        return true;
    }
    
    /**
     * 翻到下一页
     */
    public void nextPage() {
        scrollToScreen(-1, true);
    }
    
    /**
     * 翻到上一页
     */
    public void previousPage() {
        scrollToScreen(1, true);
    }

    private void scrollToScreen(float velocity, boolean isForce) {
        int startPos = getScrollX();
        int screenWidth = getWidth();
        int currentPage = startPos / screenWidth;
        int scrolledPerPage = startPos - currentPage * screenWidth;
        
        if (velocity > 0) {
            
            if (isForce) {
                if (currentPage == 0) {
                    return;
                } else {
                    scroller.startScroll(startPos, 0, -screenWidth, 0, 400);
                    currentPage--;
                }
            } else if (startPos == 0 || scrolledPerPage == 0) {
                return;
            } else {
                scroller.startScroll(startPos, 0, -scrolledPerPage, 0, 400);
            }
            
        } else if (velocity < 0){
            
            if (currentPage == (getChildCount() - 1)) {
                if (!isForce && onScreenChangeListener != null) {
                    onScreenChangeListener.moveToNext();
                }
                return;
            }
            
            scroller.startScroll(startPos, 0, screenWidth - scrolledPerPage, 0, 400);
            currentPage++;
            
        } else {
            if (scrolledPerPage < screenWidth / 2) {
                
                if (startPos == 0 || scrolledPerPage == 0) {
                    return;
                }
                
                scroller.startScroll(startPos, 0, -scrolledPerPage, 0, 400);
            } else {
                
                if (scrolledPerPage == 0) {
                    return;
                }
                
                scroller.startScroll(startPos, 0, screenWidth - scrolledPerPage, 0, 400);
                currentPage++;
            } 
        }
        invalidate();
        if (onScreenChangeListener != null) {
            if (currentPage < 0) {
                currentPage = 0;
            } else if (currentPage > (getChildCount() - 1)) {
                currentPage = getChildCount() - 1;
            }
            onScreenChangeListener.screenChange(currentPage);
        }
    }

    @Override
    public void computeScroll() {
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.getCurrX(), 0);
            postInvalidate();
        }
    }

    class GestureListener extends SimpleOnGestureListener {

        @Override
        public boolean onDoubleTap(MotionEvent e) {
            return super.onDoubleTap(e);
        }

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            
            fling = true;    
            scrollToScreen(velocityX, false);
            return true;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            super.onLongPress(e);
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            if (distanceX > 0 && getScrollX() < (getChildCount() - 1) * getWidth() || distanceX < 0
                    && getScrollX() > 0) {
                scrollBy((int) distanceX, 0);
            }
            return true;
        }

        @Override
        public void onShowPress(MotionEvent e) {
            super.onShowPress(e);
        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            return true;
        }

    }

    public interface OnScreenChangeListener {
        void screenChange(int currentTab);
        void moveToNext();
    }

    public void setOnScreenChangeListener(OnScreenChangeListener onScreenChangeListener) {
        this.onScreenChangeListener = onScreenChangeListener;
    }

}
